package com.open.capacity.reimburse.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.open.capacity.reimburse.config.OCRProperties;
import com.open.capacity.reimburse.dto.DuplicateInvoiceFilter;
import com.open.capacity.reimburse.dto.OCRInfo;
import com.open.capacity.reimburse.util.FileUtil;
import com.open.capacity.reimburse.util.pdfInvoice.*;
import com.open.capacity.reimburse.util.uuid.UUIDUtils;
import com.open.capacity.utils.DateUtil;
import com.open.capacity.utils.HttpUtil;
import com.open.capacity.utils.StringUtil;
import com.open.capacity.workflow.model.WFProcessinstance;
import com.open.capacity.workflow.service.WFProcessinstanceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.open.capacity.commons.PageResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.open.capacity.commons.CodeEnum;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

import org.apache.commons.collections4.MapUtils;
import com.open.capacity.reimburse.entity.SysInvoice;
import com.open.capacity.reimburse.dao.SysInvoiceDao;
import com.open.capacity.reimburse.service.SysInvoiceService;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@Service
public class SysInvoiceServiceImpl implements SysInvoiceService {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private SysInvoiceDao sysInvoiceDao;

    @Autowired
    private OCRProperties ocrProperties;

    @Autowired
    private WFProcessinstanceService processinstanceService;

    @Value("${file.uploadpath:/usr/local/files/upload}")
    private String fileuploadPath;

    @Override
    public int startOCR() {
        Map params = new HashMap();
        params.put("exts", Arrays.asList("png", "jpg", "jpeg"));
        params.put("imgResult", 0);
        List<SysInvoice> invoiceList = sysInvoiceDao.findAll(params);
        for (SysInvoice item : invoiceList) {
            String path = fileuploadPath + File.separator + item.getUrl().substring(item.getUrl().lastIndexOf("profile/") + 8);
            File file = new File(path);
            MultipartFile multipartFile = null;
            try {
                multipartFile = FileUtil.toMultipartFile("file", file);
            } catch (Exception e) {
                log.error("{}toMultipartFile error", item.getUrl());
            }
            String result = HttpUtil.postFile(ocrProperties.getServerUrl(), multipartFile);
            log.info(result);
            OCRInfo ocrInfo = null;
            try {
                ocrInfo = objectMapper.readValue(result, new TypeReference<OCRInfo>() {
                });
            } catch (IOException e) {
                log.error(e.getMessage());
            }
            if (ocrInfo != null) {
                item.setAmount(new BigDecimal(ocrInfo.getData().getAmount()));
                item.setCheckCode(ocrInfo.getData().getCheck());
                item.setCode(ocrInfo.getData().getCode());
                item.setNumber(ocrInfo.getData().getNumber());
                item.setDate(ocrInfo.getData().getDate());
                item.setImgResult(1);
                item.setIsVerify(1);
            } else {
                item.setImgResult(-1);
            }
            sysInvoiceDao.update(item);
        }
        return 1;
    }

    @Override
    public int startPDF() {
        Map params = new HashMap();
        params.put("pdfResult", 0);
        params.put("exts", Arrays.asList("pdf"));
        List<SysInvoice> invoiceList = sysInvoiceDao.findAll(params);
        for (SysInvoice item : invoiceList) {
            String path = fileuploadPath + File.separator + item.getUrl().substring(item.getUrl().lastIndexOf("profile/") + 8);
            File dest = new File(path);
            InvoiceExtractor invoiceExtractor = new InvoiceExtractor();
            try {
                Invoice invoice = invoiceExtractor.extract(dest);
                JSONObject json = (JSONObject) JSONObject.toJSON(invoice);
                System.out.println("解析结果：");
                System.out.println(json);

                String detailJson = "";
                //货物明细
                if (invoice.getDetailList() != null) {
                    for (Object detail : invoice.getDetailList()) {
                        //if (invoice.getType().equals("00")) {
                        //普通发票
                        Detail d = (Detail) detail;
                        if (StringUtil.isNotEmpty(d.getName())) {
                            detailJson += "【" + d.getName() + "】";
                        }
                        //}
                    }
                }

                item.setCode(invoice.getCode());
                item.setNumber(invoice.getNumber());
                item.setCheckCode(invoice.getChecksum());
                item.setDate(invoice.getDate());
                item.setAmount(invoice.getTotalAmount());
                item.setTax(invoice.getTaxAmount());
                item.setDetailJson(detailJson);
                item.setPurchaserCode(invoice.getBuyerCode());
                item.setPurchaserName(invoice.getBuyerName());
                item.setSellerCode(invoice.getSellerCode());
                item.setSellerName(invoice.getSellerName());
                item.setSellerAddress(invoice.getSellerAddress());
                item.setPdfResult(1);
                item.setIsVerify(1);
                sysInvoiceDao.update(item);


            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
        return 1;
    }

    /**
     * 添加
     *
     * @param sysInvoice
     */
    public int save(SysInvoice sysInvoice) {
        sysInvoice.setId(UUIDUtils.getOriginalUUIDWithoutBar());
        sysInvoice.setIsVerify(0);
        sysInvoice.setPdfResult(0);
        sysInvoice.setImgResult(0);
        sysInvoice.setUpdateTime(new Date());
        return sysInvoiceDao.save(sysInvoice);
    }

    /**
     * 修改
     *
     * @param sysInvoice
     */
    public int update(SysInvoice sysInvoice) {
        sysInvoice.setUpdateTime(new Date());
        return sysInvoiceDao.update(sysInvoice);
    }

    @Override
    public int duplicateCheck() {
        Map params = new HashMap();
        params.put("pdfResult", 1);
        List<SysInvoice> invoiceList = sysInvoiceDao.findAll(params);
        List<SysInvoice> duplicates = DuplicateInvoiceFilter.getDuplicates(invoiceList);
        return duplicates.size();
    }

    /**
     * 清理没有流程号的发票
     */
    public int clearNoProcess() {
        //删除多余的发票
        sysInvoiceDao.clearNoProcessCode(DateUtil.getCurrentDay(DateUtil.DATE));

        //检测是否重复
        Map params = new HashMap();
        params.put("pdfResult", 1);
        List<SysInvoice> invoiceList = sysInvoiceDao.findAll(params);
        List<SysInvoice> duplicates = DuplicateInvoiceFilter.getDuplicates(invoiceList);
        for (SysInvoice item : invoiceList) {
            duplicates.forEach(t -> {
                if (t.getNumber().equals(item.getNumber())) {
                    item.setIsDuplicate(1);
                    sysInvoiceDao.update(item);
                }
            });
        }
        return 1;
    }

    /**
     * 删除
     *
     * @param id
     */
    public int delete(String id) {
        return sysInvoiceDao.delete(id);
    }

    /**
     * 查询记录
     *
     * @param id
     * @return
     */
    public SysInvoice findById(String id) {
        return sysInvoiceDao.findById(id);
    }

    /**
     * 分页
     *
     * @param params
     * @return
     */
    public PageResult<SysInvoice> pageAll(Map<String, Object> params) {
        //设置分页信息，分别是当前页数和每页显示的总记录数【记住：必须在mapper接口中的方法执行之前设置该分页信息】
        if (MapUtils.getInteger(params, "page") != null && MapUtils.getInteger(params, "limit") != null)
            PageHelper.startPage(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"), true);

        List<SysInvoice> list = sysInvoiceDao.findAll(params);
        list.forEach(item -> {
            WFProcessinstance processinstance = processinstanceService.findById(item.getProcessId());
            if (processinstance != null) {
                item.setProcessCode(processinstance.getCode());
                item.setProcessName(processinstance.getProcessName());
            }
        });
        PageInfo<SysInvoice> pageInfo = new PageInfo(list);

        return PageResult.<SysInvoice>builder().data(pageInfo.getList()).resp_code(CodeEnum.SUCCESS.getCode()).count(pageInfo.getTotal()).build();
    }

    /**
     * 列表
     *
     * @param params
     * @return
     */
    public List<SysInvoice> findAll(Map<String, Object> params) {
        return sysInvoiceDao.findAll(params);
    }
}
